package kiwi.core.services.async;

import kiwi.core.qualifiers.async.Asynchronous;
import org.slf4j.Logger;

import javax.inject.Inject;
import javax.interceptor.AroundInvoke;
import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext;
import java.util.UUID;

/**
 * This interceptor wraps a method invocation of a method annotated with @Asynchronous in a separate, newly created
 * thread.
 * <p/>
 * User: sschaffe
 */
@Asynchronous @Interceptor
public class AsynchronousInterceptor {

    @Inject
    private Logger log;


    private static final ThreadGroup asyncMethods = new ThreadGroup("asynchronous method invocations");


    @AroundInvoke
    public Object manageAsynchronous(final InvocationContext ctx) throws Exception {

        final UUID threadID = UUID.randomUUID();


        Runnable r = new Runnable() {
            @Override
            public void run() {
                try {
                    log.debug("asynchronous method invocation of {}.{} (Thread ID {})",new Object[] {ctx.getTarget().getClass().getName(),ctx.getMethod().getName(), threadID});
                    Object val = ctx.proceed();

                    if(val != null) {
                        log.debug("asynchronous method invocation of {}.{} (Thread ID {}) returned value {}",new Object[] {ctx.getClass().getName(),ctx.getMethod().getName(), threadID, val});
                    }
                } catch(Exception ex) {
                    log.error("exception during asynchronous method invocation",ex);
                }
            }
        };

        Thread t = new Thread(asyncMethods,r);
        t.setName("asynchronous method invocation of "+ctx.getTarget().getClass().getName()+ctx.getMethod().getName() + " (Threaad ID " + threadID+")");
        t.start();

        return null;
    }


}
